#include <iostream>
#include <cassert>
#include <unordered_map>
#include "ast.hpp"

static int koopacnt = 0;//koopa个数，返回值
static bool control_flow_terminated = false;//是否存在ret
static int ifcnt = 0;// if 的个数，用于设置 entry
static int whilecnt = 0;
static std::vector<int> while_stack;//记录层级
static int gloval_var = 0;// 是否在声明全局变量

/************************CompUnit*************************/

// CompUnit ::= FuncDef
void CompUnitAST::KoopaIR() const {
  enter_code_block();
  std::cout << "decl @getint(): i32\n" \
               "decl @getch(): i32\n" \
               "decl @getarray(*i32): i32\n" \
               "decl @putint(i32)\n" \
               "decl @putch(i32)\n" \
               "decl @putarray(i32, *i32)\n" \
               "decl @starttime()\n" \
               "decl @stoptime()\n" << std::endl;
  insert_symbol("getint", SYM_TYPE_FUNCINT, 0);
  insert_symbol("getch", SYM_TYPE_FUNCINT, 0);
  insert_symbol("getarray", SYM_TYPE_FUNCINT, 0);
  insert_symbol("putint", SYM_TYPE_FUNCVOID, 0);
  insert_symbol("putch", SYM_TYPE_FUNCVOID, 0);
  insert_symbol("putarray", SYM_TYPE_FUNCVOID, 0);
  insert_symbol("starttime", SYM_TYPE_FUNCVOID, 0);
  insert_symbol("stoptime", SYM_TYPE_FUNCVOID, 0);
  for(auto& comp_unit_item: *comp_unit_item_list) {
    comp_unit_item->KoopaIR();
    std::cout << std::endl;
  }
  exit_code_block();
}

// CompUnitItem ::= FuncDef;
void CompUnitItemAST::KoopaIR() const {
    if(type==1) {
    gloval_var = 1;
    decl1_funcdef2->KoopaIR();
    gloval_var = 0;
  }
  else if(type==2) {
    decl1_funcdef2->KoopaIR();
  }
}

/**************************Decl***************************/

// Decl ::= ConstDecl | VarDecl;
void DeclAST::KoopaIR() const {
  if (const_decl1_var_decl2) const_decl1_var_decl2->KoopaIR();
}

// ConstDecl ::= "const" BType ConstDefList ";";
// ConstDefList ::= ConstDef | ConstDefList "," ConstDef;
void ConstDeclAST::KoopaIR() const {
  if (const_def_list) {
    for (const auto& const_def : *const_def_list) {
      if (const_def) const_def->KoopaIR();
    }
  }
}


// ConstDef ::= IDENT "=" ConstInitVal;
void ConstDefAST::KoopaIR() const {
  if (const_init_val) {
    insert_symbol(ident, SYM_TYPE_CONST,
                  dynamic_cast<ConstInitValAST*>(const_init_val.get())->Calc());
  }
}

// ConstInitVal ::= ConstExp;
void ConstInitValAST::KoopaIR() const {
  assert(false && "ConstInitValAST::KoopaIR() should not be called");
}

int ConstInitValAST::Calc() const {
  return const_exp ? dynamic_cast<ExpBaseAST*>(const_exp.get())->Calc() : 0;
}

// VarDecl ::= BType VarDefList ";";
// VarDefList ::= VarDef | VarDefList "," VarDef;
void VarDeclAST::KoopaIR() const {
  if (var_def_list) {
    for (const auto& var_def : *var_def_list) {
      if (var_def) var_def->KoopaIR();
    }
  }
}

// VarDef ::= IDENT | IDENT "=" InitVal;
void VarDefAST::KoopaIR() const {
    // 插入符号
    insert_symbol(ident, SYM_TYPE_VAR, 0);

    // 分配内存
    std::string allocCmd = " = alloc i32";
    if (gloval_var) { // 全局变量
        std::cout << "global @" << current_code_block() << ident << allocCmd;
        if (type == 1) {
            std::cout << ", zeroinit" << std::endl;
        } else if (type == 2) {
            std::cout << ", ";
            std::cout << dynamic_cast<InitValAST*>(init_val.get())->Calc() << std::endl;
        }
        std::cout << std::endl;
    } else { // 局部变量
        std::cout << "  @" << current_code_block() << ident << allocCmd << std::endl;
        if (type == 2 && init_val) {
            init_val->KoopaIR();
            std::cout << "  store %" << koopacnt - 1 << ", @";
            std::cout << query_symbol(ident).first << ident << std::endl;
        }
    }
}


// InitVal ::= Exp;
void InitValAST::KoopaIR() const {
  if (exp) exp->KoopaIR();
}
int InitValAST::Calc() const {
  return dynamic_cast<ExpBaseAST*>(exp.get())->Calc();
}


/**************************Func***************************/

// FuncDef ::= FuncType IDENT "(" ")" Block;
void FuncDefAST::KoopaIR() const {
    // 根据函数类型插入符号
    switch (func_type[0]) {
        case 'v': // void
            insert_symbol(ident, SYM_TYPE_FUNCVOID, 0);
            break;
        case 'i': // int
            insert_symbol(ident, SYM_TYPE_FUNCINT, 0);
            break;
        default:
            assert(false && "Unknown function type");
    }
    enter_code_block();
    // 打印函数头部信息
    std::cout << "fun @" << ident << "(";
    if (!func_f_param_list->empty()) {
        for (size_t i = 0; i < func_f_param_list->size(); ++i) {
            (*func_f_param_list)[i]->KoopaIR();
            if (i < func_f_param_list->size() - 1) {
                std::cout << ", ";
            }
        }
    }
    std::cout << ")";
    if (func_type == "int") {
        std::cout << ": i32 ";
    }
    std::cout << " {\n";
    std::cout << "%entry:\n";
    // 为函数参数分配内存
    for (const auto& func_f_param : *func_f_param_list) {
        dynamic_cast<FuncFParamAST*>(func_f_param.get())->Alloc();
    }
    // 处理函数体
    block->KoopaIR();
    // 如果没有终止的控制流语句，补充默认返回值
    if (!control_flow_terminated) {
        switch (func_type[0]) {
            case 'i': // int
                std::cout << "  ret 0\n";
                break;
            case 'v': // void
                std::cout << "  ret\n";
                break;
            default:
                assert(false && "Unhandled return type");
        }
    }
    std::cout << "}\n\n";
    exit_code_block();
}

  
void FuncFParamAST::KoopaIR() const {
  std::cout << "@" << ident << ": i32";
}
void FuncFParamAST::Alloc() const {
  std::cout << "  @" << current_code_block() << ident << " = alloc i32" << std::endl;
  insert_symbol(ident, SYM_TYPE_VAR, 0);
  std::cout << "  store @" << ident << ", @";
  std::cout << query_symbol(ident).first << ident << std::endl;
}

/**************************Block***************************/

// Block ::= "{" BlockItemList "}";
// BlockItemList ::=  | BlockItemList BlockItem;
void BlockAST::KoopaIR() const {
  enter_code_block();
  control_flow_terminated = false;
  for(auto& block_item: *block_item_list)
  {
    block_item->KoopaIR();
    if (control_flow_terminated) {
      break;
    }
  }
  exit_code_block();
}

// BlockItem ::= Decl | Stmt;
void BlockItemAST::KoopaIR() const {
  decl1_stmt2->KoopaIR();
}

void StmtAST::KoopaIR() const {

  switch (type) {
    case 1:
      exp->KoopaIR();
      store_to_lval();
      break;
    case 2:
      exp->KoopaIR();
      break;
    case 3:
      break;
    case 4:
      lval1_block4->KoopaIR();
      break;
    case 5:
      exp->KoopaIR();
      std::cout << "  ret %" << koopacnt - 1 << std::endl;
      control_flow_terminated = true;
      break;
    case 6:
      std::cout << "  ret" << std::endl;
      control_flow_terminated = true;
      break;
    default:
      assert(false && "Unknown statement type");
  }
}
//将表达式结果存储到左值中
void StmtAST::store_to_lval() const {
  const std::string& ident = dynamic_cast<LValAST*>(lval1_block4.get())->ident;
  std::cout << "  store %" << koopacnt - 1 << ", @";
  std::cout << query_symbol(ident).first << ident << std::endl;
}
void IfStmtAST::KoopaIR() const {
  if (control_flow_terminated) return;
  if(type==1||2){
    int current_if = ifcnt++;
    exp->KoopaIR();
    std::string label_then = "%STMTIF_THEN_" + std::to_string(current_if);
    std::string label_end = "%STMTIF_END_" + std::to_string(current_if);
    if (type == 1) { // 普通的 if
        std::cout << "  br %" << koopacnt - 1 << ", " << label_then << ", " << label_end << std::endl;
        std::cout << label_then << ":" << std::endl;
        control_flow_terminated = false;
        if_stmt->KoopaIR();
        if (control_flow_terminated!=true) {
            std::cout << "  jump " << label_end << std::endl;
        }
        std::cout << label_end << ":" << std::endl;
        control_flow_terminated = false;
    } else if (type == 2) { // 带 else 的 if
        std::string label_else = "%STMTIF_ELSE_" + std::to_string(current_if);
        std::cout << "  br %" << koopacnt - 1 << ", " << label_then << ", " << label_else << std::endl;
        std::cout << label_then << ":" << std::endl;
        control_flow_terminated = false;
        if_stmt->KoopaIR();
        if (control_flow_terminated!=true) {
            std::cout << "  jump " << label_end << std::endl;
        }
        std::cout << label_else << ":" << std::endl;
        control_flow_terminated = false;
        else_stmt->KoopaIR();
        if (control_flow_terminated!=true) {
            std::cout << "  jump " << label_end << std::endl;
        }
        std::cout << label_end << ":" << std::endl;
        control_flow_terminated = false;
    }
  }
if (type == 3) {
  if (control_flow_terminated) return;
  std::string entry_label = "%STMTWHILE_ENTRY_" + std::to_string(whilecnt);
  std::string body_label = "%STMTWHILE_BODY_" + std::to_string(whilecnt);
  std::string end_label = "%STMTWHILE_END_" + std::to_string(whilecnt);
  while_stack.push_back(whilecnt++);
  //跳到条目标签开始循环
  std::cout << "  jump " << entry_label << std::endl;
  // 入口i
  std::cout << entry_label << ":" << std::endl;
  exp->KoopaIR();
  std::cout << "  br %" << koopacnt - 1 << ", " << body_label << ", " << end_label << std::endl;
  //循环体
  std::cout << body_label << ":" << std::endl;
  bool original_control_flow_terminated = control_flow_terminated;
  control_flow_terminated = false;
  while_stmt->KoopaIR();
  //如果未终止，则跳回下一次的条目标签
  if (!control_flow_terminated) {
    std::cout << "  jump " << entry_label << std::endl;
  }
  // End
  std::cout << end_label << ":" << std::endl;
  control_flow_terminated = original_control_flow_terminated;
  while_stack.pop_back();
}
}
void BCStmtAST::KoopaIR() const {
  if (type == 1)
      {
        assert(!while_stack.empty());
        int while_no = while_stack.back();
        std::string end_label = "%STMTWHILE_END_" + std::to_string(while_no);
        std::cout << "\tjump " << end_label << std::endl;
        control_flow_terminated=1;
      }else if (type == 2)
      {
        assert(!while_stack.empty());
        int while_no = while_stack.back();
        std::string entry_label = "%STMTWHILE_ENTRY_" +std::to_string(while_no);
        std::cout << "\tjump " << entry_label << std::endl;
        control_flow_terminated=1;
      }
  }
/***************************Exp***************************/

// 生成二进制操作Koopa IR指令
void generate_binop(const std::string& op, int left, int right) {
    std::cout << "  %" << koopacnt << " = " << op << " %" << left << ", %" << right << std::endl;
    koopacnt++;
}

// 生成Koopa IR指令以进行比较操作
void generate_cmpop(const std::string& op, int left, int right) {
    std::cout << "  %" << koopacnt << " = " << op << " %" << left << ", %" << right << std::endl;
    koopacnt++;
}

// 为常数生成Koopa IR指令
void generate_const(int value) {
    std::cout << "  %" << koopacnt << " = add 0, " << value << std::endl;
    koopacnt++;
}

// Exp ::= LOrExp;
void ExpAST::KoopaIR() const {
  lorexp->KoopaIR();
}

int ExpAST::Calc() const {
  return dynamic_cast<ExpBaseAST*>(lorexp.get())->Calc();
}

// LVal ::= IDENT;
void LValAST::KoopaIR() const {
    auto val = query_symbol(ident);
    assert(val.second->type != SYM_TYPE_UND);

    if (val.second->type == SYM_TYPE_CONST) {
        generate_const(val.second->value);
    } else if (val.second->type == SYM_TYPE_VAR) {
        std::cout << "  %" << koopacnt << " = load @" << val.first << ident << std::endl;
        koopacnt++;
    }
}

int LValAST::Calc() const {
    auto val = query_symbol(ident);
    assert(val.second->type == SYM_TYPE_CONST);
    return val.second->value;
}

// PrimaryExpAST
void PrimaryExpAST::KoopaIR() const {
    if (type == 1 || type == 2) {
        exp1_lval2->KoopaIR();
    } else if (type == 3) {
        generate_const(number);
    }
}

int PrimaryExpAST::Calc() const {
    if (type == 1 || type == 2) {
        return dynamic_cast<ExpBaseAST*>(exp1_lval2.get())->Calc();
    } else if (type == 3) {
        return number;
    }
    assert(0);
    return 0;
}

// UnaryExpAST
void UnaryExpAST::KoopaIR() const {
    switch (type) {
        case 1: {
            primaryexp1_unaryexp2->KoopaIR();
            break;
        }
        case 2: {
            primaryexp1_unaryexp2->KoopaIR();
            switch (unaryop) {
                case '-': {
                    std::cout << "  %" << koopacnt << " = sub 0, %";
                    std::cout << koopacnt - 1 << std::endl;
                    koopacnt++;
                    break;
                }
                case '!': {
                    std::cout << "  %" << koopacnt << " = eq 0, %";
                    std::cout << koopacnt - 1 << std::endl;
                    koopacnt++;
                    break;
                }
                default: {
                    assert(false && "Unhandled unary operator");
                }
            }
            break;
        }
        case 3: {
            auto func = query_symbol(ident);
            // 必须为全局符号
            assert(func.first == "SYM_TABLE_0_");
            // 必须是函数
            assert(func.second->type == SYM_TYPE_FUNCVOID || func.second->type == SYM_TYPE_FUNCINT);
            // 计算所有的参数
            std::vector<int> vec;
            for (auto& exp : *func_r_param_list) {
                exp->KoopaIR();
                vec.push_back(koopacnt - 1);
            }
            // 如果是 int 函数，把返回值保存下来
            if (func.second->type == SYM_TYPE_FUNCINT) {
                std::cout << "  %" << koopacnt << " = ";
            } else if (func.second->type == SYM_TYPE_FUNCVOID) {
                std::cout << "  ";
            }
            // call @func(%1, %2)
            std::cout << "call @" << ident << "(";
            for (size_t i = 0; i < vec.size(); ++i) {
                std::cout << "%" << vec[i];
                if (i < vec.size() - 1) {
                    std::cout << ", ";
                }
            }
            std::cout << ")" << std::endl;
            if (func.second->type == SYM_TYPE_FUNCINT) {
                koopacnt++;
            }
            break;
        }
        default: {
            assert(false && "Unknown type in UnaryExpAST");
        }
    }
}


int UnaryExpAST::Calc() const {
    if (type == 1) {
        return dynamic_cast<ExpBaseAST*>(primaryexp1_unaryexp2.get())->Calc();
    } else if (type == 2) {
        int tmp = dynamic_cast<ExpBaseAST*>(primaryexp1_unaryexp2.get())->Calc();
        if (unaryop == '+') return tmp;
        else if (unaryop == '-') return -tmp;
        else if (unaryop == '!') return !tmp;
    }
    assert(0);
    return 0;
}

// MulExpAST
void MulExpAST::KoopaIR() const {
    if (type == 1) {
        unaryexp->KoopaIR();
    } else if (type == 2) {
        mulexp->KoopaIR();
        int left = koopacnt - 1;
        unaryexp->KoopaIR();
        int right = koopacnt - 1;

        if (mulop == '*') {
            generate_binop("mul", left, right);
        } else if (mulop == '/') {
            generate_binop("div", left, right);
        } else if (mulop == '%') {
            generate_binop("mod", left, right);
        }
    }
}

int MulExpAST::Calc() const {
    if (type == 1) {
        return dynamic_cast<ExpBaseAST*>(unaryexp.get())->Calc();
    } else if (type == 2) {
        int left = dynamic_cast<ExpBaseAST*>(mulexp.get())->Calc();
        int right = dynamic_cast<ExpBaseAST*>(unaryexp.get())->Calc();

        if (mulop == '*') return left * right;
        else if (mulop == '/') return left / right;
        else if (mulop == '%') return left % right;
    }
    assert(0);
    return 0;
}

// AddExp ::= MulExp | AddExp AddOp MulExp;
void AddExpAST::KoopaIR() const {
    if (type == 1) {
        mulexp->KoopaIR();
    } else if (type == 2) {
        addexp->KoopaIR();
        int left = koopacnt - 1;
        mulexp->KoopaIR();
        int right = koopacnt - 1;

        if (addop == '+') {
            generate_binop("add", left, right);
        } else if (addop == '-') {
            generate_binop("sub", left, right);
        }
    }
}

int AddExpAST::Calc() const {
    if (type == 1) {
        return dynamic_cast<ExpBaseAST*>(mulexp.get())->Calc();
    } else if (type == 2) {
        int left = dynamic_cast<ExpBaseAST*>(addexp.get())->Calc();
        int right = dynamic_cast<ExpBaseAST*>(mulexp.get())->Calc();
        if (addop == '+') return left + right;
        else if (addop == '-') return left - right;
    }
    assert(0);
    return 0;
}
// RelExp ::= AddExp | RelExp RelOp AddExp;
void RelExpAST::KoopaIR() const {
    if (type == 1) {
        addexp->KoopaIR();
    } else if (type == 2) {
        relexp->KoopaIR();
        int left = koopacnt - 1;
        addexp->KoopaIR();
        int right = koopacnt - 1;

        if (relop == "<") {
            generate_cmpop("lt", left, right);
        } else if (relop == ">") {
            generate_cmpop("gt", left, right);
        } else if (relop == "<=") {
            generate_cmpop("le", left, right);
        } else if (relop == ">=") {
            generate_cmpop("ge", left, right);
        } else if (relop == "==") {
            generate_cmpop("eq", left, right);
        } else if (relop == "!=") {
            generate_cmpop("ne", left, right);
        }
    }
}

int RelExpAST::Calc() const {
    if (type == 1) {
        return dynamic_cast<ExpBaseAST*>(addexp.get())->Calc();
    } else if (type == 2) {
        int left = dynamic_cast<ExpBaseAST*>(relexp.get())->Calc();
        int right = dynamic_cast<ExpBaseAST*>(addexp.get())->Calc();

        if (relop == "<") return left < right;
        else if (relop == ">") return left > right;
        else if (relop == "<=") return left <= right;
        else if (relop == ">=") return left >= right;
        else if (relop == "==") return left == right;
        else if (relop == "!=") return left != right;
    }
    assert(0);
    return 0;
}

// EqExp ::= RelExp | EqExp EqOp RelExp
void EqExpAST::KoopaIR() const {
    if (type == 1) {
        relexp->KoopaIR();
    } else if (type == 2) {
        eqexp->KoopaIR();
        int left = koopacnt - 1;
        relexp->KoopaIR();
        int right = koopacnt - 1;

        if (eqop == "==") {
            generate_cmpop("eq", left, right);
        } else if (eqop == "!=") {
            generate_cmpop("ne", left, right);
        }
    }
}

int EqExpAST::Calc() const {
    if (type == 1) {
        return dynamic_cast<ExpBaseAST*>(relexp.get())->Calc();
    } else if (type == 2) {
        int left = dynamic_cast<ExpBaseAST*>(eqexp.get())->Calc();
        int right = dynamic_cast<ExpBaseAST*>(relexp.get())->Calc();
        if (eqop == "==") {
            return left == right;
        } else if (eqop == "!=") {
            return left != right;
        }
    }
    assert(0);
    return 0;
}


// LAndExp ::= EqExp | LAndExp "&&" EqExp;
void LAndExpAST::KoopaIR() const {
    if (type == 1) {
        eqexp->KoopaIR();
        return;
    }

    // 处理 "&&" 情况
    landexp->KoopaIR();
    int tmp_var = koopacnt++;
    std::cout << "  %" << tmp_var << " = ne %" << (tmp_var - 1) << ", 0" << std::endl;

    int current_if = ifcnt++;
    std::string result_var = "@STMTIF_LAND_RESULT_" + std::to_string(current_if);
    std::string label_then = "%STMTIF_THEN_" + std::to_string(current_if);
    std::string label_else = "%STMTIF_ELSE_" + std::to_string(current_if);
    std::string label_end = "%STMTIF_END_" + std::to_string(current_if);

    std::cout << "  " << result_var << " = alloc i32" << std::endl;
    std::cout << "  br %" << (tmp_var) << ", " << label_then << ", " << label_else << std::endl;
    // THEN block
    std::cout << label_then << ":" << std::endl;
    control_flow_terminated = false;
    eqexp->KoopaIR();
    int tmp_then = koopacnt++;
    std::cout << "  %" << tmp_then << " = ne %" << (tmp_then - 1) << ", 0" << std::endl;
    std::cout << "  store %" << tmp_then << ", " << result_var << std::endl;
    if (!control_flow_terminated) {
        std::cout << "  jump " << label_end << std::endl;
    }
    // ELSE block
    std::cout << label_else << ":" << std::endl;
    control_flow_terminated = false;
    std::cout << "  store 0, " << result_var << std::endl;
    if (!control_flow_terminated) {
        std::cout << "  jump " << label_end << std::endl;
    }
    // END block
    std::cout << label_end << ":" << std::endl;
    control_flow_terminated = false;
    int tmp_end = koopacnt++;
    std::cout << "  %" << tmp_end << " = load " << result_var << std::endl;
}


int LAndExpAST::Calc() const {
  if(type==1) {
    return dynamic_cast<ExpBaseAST*>(eqexp.get())->Calc();
  }
  else if(type==2) {
    int left = dynamic_cast<ExpBaseAST*>(landexp.get())->Calc();
    if(!left) return 0;
    int right = dynamic_cast<ExpBaseAST*>(eqexp.get())->Calc();
    return (right!=0);
  }
  assert(0);
  return 0;
}

// LOrExp ::= LAndExp | LOrExp "||" LAndExp;
void LOrExpAST::KoopaIR() const {
    if (type == 1) {
        landexp->KoopaIR();
        return;
    }

    // 处理 "||" 情况
    lorexp->KoopaIR();
    int tmp_var = koopacnt++;
    std::cout << "  %" << tmp_var << " = ne %" << (tmp_var - 1) << ", 0" << std::endl;

    int current_if = ifcnt++;
    std::string result_var = "@STMTIF_LOR_RESULT_" + std::to_string(current_if);
    std::string label_then = "%STMTIF_THEN_" + std::to_string(current_if);
    std::string label_else = "%STMTIF_ELSE_" + std::to_string(current_if);
    std::string label_end = "%STMTIF_END_" + std::to_string(current_if);

    std::cout << "  " << result_var << " = alloc i32" << std::endl;
    std::cout << "  br %" << (tmp_var) << ", " << label_then << ", " << label_else << std::endl;
    // THEN block
    std::cout << label_then << ":" << std::endl;
    control_flow_terminated = false;
    std::cout << "  store 1, " << result_var << std::endl;
    if (!control_flow_terminated) {
        std::cout << "  jump " << label_end << std::endl;
    }
    // ELSE block
    std::cout << label_else << ":" << std::endl;
    control_flow_terminated = false;
    landexp->KoopaIR();
    int tmp_else = koopacnt++;
    std::cout << "  %" << tmp_else << " = ne %" << (tmp_else - 1) << ", 0" << std::endl;
    std::cout << "  store %" << tmp_else << ", " << result_var << std::endl;
    if (!control_flow_terminated) {
        std::cout << "  jump " << label_end << std::endl;
    }
    // END block
    std::cout << label_end << ":" << std::endl;
    control_flow_terminated = false;
    int tmp_end = koopacnt++;
    std::cout << "  %" << tmp_end << " = load " << result_var << std::endl;
}


int LOrExpAST::Calc() const {
  if(type==1) {
    return dynamic_cast<ExpBaseAST*>(landexp.get())->Calc();
  }
  else if(type==2) {
    int left = dynamic_cast<ExpBaseAST*>(lorexp.get())->Calc();
    if(left) return 1;
    int right = dynamic_cast<ExpBaseAST*>(landexp.get())->Calc();
    return (right!=0);
  }
  assert(0);
  return 0;
}

// ConstExp ::= Exp;
void ConstExpAST::KoopaIR() const {
  assert(0);
  return;
}

int ConstExpAST::Calc() const {
  return dynamic_cast<ExpBaseAST*>(exp.get())->Calc();
}